package com.unswift.cloud.service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiEntity;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import com.unswift.api.ApiHandle;
import com.unswift.cloud.adapter.system.api.SystemApiClassAdapter;
import com.unswift.cloud.adapter.system.api.SystemApiConstructorAdapter;
import com.unswift.cloud.adapter.system.api.SystemApiFieldAdapter;
import com.unswift.cloud.adapter.system.api.SystemApiMethodAdapter;
import com.unswift.cloud.adapter.system.api.SystemApiVersionAdapter;
import com.unswift.cloud.pojo.bo.system.api.classes.SystemApiClassPageBo;
import com.unswift.cloud.pojo.bo.system.api.classes.SystemApiClassViewBo;
import com.unswift.cloud.pojo.dao.system.api.classes.SystemApiClassDataDo;
import com.unswift.cloud.pojo.dao.system.api.classes.SystemApiClassInsertDo;
import com.unswift.cloud.pojo.dao.system.api.classes.SystemApiClassPageDo;
import com.unswift.cloud.pojo.dao.system.api.classes.SystemApiClassSingleDo;
import com.unswift.cloud.pojo.dao.system.api.constructor.SystemApiConstructorInsertBatchItemDo;
import com.unswift.cloud.pojo.dao.system.api.field.SystemApiFieldInsertBatchItemDo;
import com.unswift.cloud.pojo.dao.system.api.method.SystemApiMethodInsertBatchItemDo;
import com.unswift.cloud.pojo.dto.BaseDto;
import com.unswift.cloud.pojo.vo.page.IPageVo;
import com.unswift.cloud.pojo.vo.page.PageVo;
import com.unswift.cloud.pojo.vo.system.api.classes.SystemApiClassPageVo;
import com.unswift.cloud.pojo.vo.system.api.classes.SystemApiClassProgressVo;
import com.unswift.cloud.pojo.vo.system.api.classes.SystemApiClassSynchVo;
import com.unswift.cloud.pojo.vo.system.api.classes.SystemApiClassViewVo;
import com.unswift.cloud.queue.IQueueTaskHandle;
import com.unswift.cloud.queue.LocalSecurityQueue;
import com.unswift.cloud.queue.QueueTask;
import com.unswift.exception.CoreException;
import com.unswift.utils.ClassUtils;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.ObjectUtils;

@Service
@Api(value="类api服务", author="unswift", date="2023-09-05", version="1.0.0")
public class SystemApiClassService extends BaseService implements IQueueTaskHandle<BaseDto>{
	
	@Autowired
	@ApiField("类api公共服务")
	private SystemApiClassAdapter systemApiClassAdapter;
	
	@Autowired
	@ApiField("类api版本公共服务")
	private SystemApiVersionAdapter systemApiVersionAdapter;
	
	@Autowired
	@ApiField("类api字段公共服务")
	private SystemApiFieldAdapter systemApiFieldAdapter;
	
	@Autowired
	@ApiField("类api构造函数公共服务")
	private SystemApiConstructorAdapter systemApiConstructorAdapter;
	
	@Autowired
	@ApiField("类api方法公共服务")
	private SystemApiMethodAdapter systemApiMethodAdapter;
	
	@Autowired
	@ApiField("本服务队列")
	private LocalSecurityQueue localSecurityQueue;
	
	@Autowired
	@ApiField("api处理类")
	private ApiHandle apiHandle;
	
	@ApiField("是否又任务执行")
	private Boolean isHaveTask=false;
	
	@ApiField("错误消息，如果发生异常")
	private String errorMessage;
	
	@ApiField("执行进度，0-100")
	private Integer progress=0;
	
	@ApiMethod(value="查询类api分页数据", params=@ApiField("分页对象，包含分页信息及查询条件"), returns=@ApiField("包含查询数据的分页对象"))
	public IPageVo<SystemApiClassPageVo> findPageList(SystemApiClassPageBo searchBo){
		SystemApiClassPageDo search=this.convertPojo(searchBo, SystemApiClassPageDo.class);//将Bo转换为Do
		search.setFirstSize((search.getCurrPage()-1)*search.getPageSize());
		PageVo<SystemApiClassDataDo> page=systemApiClassAdapter.findPageList(search);//将Do转换为Vo
		return this.convertPage(page, SystemApiClassPageVo.class);
	}
	
	@ApiMethod(value="查询类api详情", params=@ApiField("详情业务实体，包含id字段"), returns=@ApiField("类api详情数据"))
	public SystemApiClassViewVo view(SystemApiClassViewBo viewBo){
		SystemApiClassSingleDo search=this.convertPojo(viewBo, SystemApiClassSingleDo.class);
		SystemApiClassDataDo single=systemApiClassAdapter.findSingle(search);
		return this.convertPojo(single, SystemApiClassViewVo.class);//将Do转换为Vo
	}

	@ApiMethod(value="类api同步，把API注解写入数据库", returns=@ApiField("类api详情数据"))
	public SystemApiClassSynchVo synch(){
		if(isHaveTask) {
			throw ExceptionUtils.message("task.is.currently.executing", ExceptionUtils.getMessage("keyword.synchronous"));
		}
		isHaveTask=true;
		progress=1;
		errorMessage=null;
		QueueTask<BaseDto> task=new QueueTask<BaseDto>();
		task.setTaskBean(this);
		task.setTaskData(null);
		localSecurityQueue.offer(task);
		return new SystemApiClassSynchVo(1);
	}
	
	@Override
	@SuppressWarnings("unchecked")
	@ApiMethod(value="处理队列任务", params = @ApiField("传递的参数，此处为null"))
	@Transactional("systemTransactionManager")
	public void handle(BaseDto data) {
		try {
			List<Class<?>> apiClassList=apiHandle.getApiClassList(ObjectUtils.asList(Api.class,ApiEntity.class));
			progress=5;
			if(ObjectUtils.isEmpty(apiClassList)) {
				return ;
			}
			Api apiAnno;
			ApiEntity apiEntityAnno;
			SystemApiClassInsertDo apiClassDo;
			List<SystemApiFieldInsertBatchItemDo> fieldList;
			List<SystemApiConstructorInsertBatchItemDo> constructorList;
			List<SystemApiMethodInsertBatchItemDo> methodList;
			int index=1, length=apiClassList.size();
			for (Class<?> apiClass : apiClassList) {
				apiAnno=apiClass.getAnnotation(Api.class);
				apiEntityAnno=apiClass.getAnnotation(ApiEntity.class);
				if(ObjectUtils.isNotEmpty(apiAnno)) {
					apiClassDo=systemApiClassAdapter.handleApiAnno(apiAnno, apiClass);
					systemApiVersionAdapter.handleVersionsAnno(apiAnno.versionAppend(), apiClassDo.getId(), "system_api_class_");
				}else if(ObjectUtils.isNotEmpty(apiEntityAnno)) {
					apiClassDo=systemApiClassAdapter.handleApiAnno(apiEntityAnno, apiClass);
					systemApiVersionAdapter.handleVersionsAnno(apiEntityAnno.versionAppend(), apiClassDo.getId(), "system_api_class_");
				}else {
					progress=5+new BigDecimal((index*100.0)/length).setScale(0, RoundingMode.DOWN).intValue();
					index++;
					continue;
				}
				if(!apiClassDo.getIsChange()) {
					progress=5+new BigDecimal((index*100.0)/length).setScale(0, RoundingMode.DOWN).intValue();
					index++;
					continue;
				}
				//删除类下面的所有版本信息
				systemApiVersionAdapter.deleteByClassId(apiClassDo.getId());
				systemApiFieldAdapter.deleteByClassId(apiClassDo.getId());
				//field
				fieldList=systemApiFieldAdapter.handleClassFieldList(ClassUtils.getFieldList(apiClass), apiClassDo.getId(), "system_api_class_");;
				systemApiVersionAdapter.handleVersionsAnno(fieldList);
				//constructor
				constructorList=systemApiConstructorAdapter.handleConstructorAnno(apiClass.getConstructors(), apiClassDo.getId());
				systemApiVersionAdapter.handleConstructorVersionsAnno(constructorList);
				//constructor params
				fieldList=systemApiFieldAdapter.handleConstructorParam(constructorList);
				systemApiVersionAdapter.handleVersionsAnno(fieldList);
				//method
				methodList = systemApiMethodAdapter.handleMethodAnno(apiClass.getDeclaredMethods(), apiClassDo.getId());
				systemApiVersionAdapter.handleMethodVersionsAnno(methodList);
				//method params returns
				fieldList=systemApiFieldAdapter.handleMethod(methodList);
				systemApiVersionAdapter.handleVersionsAnno(fieldList);
				progress=5+new BigDecimal((index*100.0)/length).setScale(0, RoundingMode.DOWN).intValue();
				index++;
			}
		} catch (CoreException e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
			errorMessage=e.getMessage();
			throw e;
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
			errorMessage=e.getMessage();
			throw e;
		} finally {
			progress=100;
			isHaveTask=false;
		}
	}
	
	public SystemApiClassProgressVo getSynchProgress() {
		if(progress>=100) {
			progress=0;
			String backMessage=errorMessage;
			errorMessage=null;
			return new SystemApiClassProgressVo(100, backMessage);
		}else {
			return new SystemApiClassProgressVo(progress, errorMessage);
		}
	}
}
